package com.wsd.jing.service.impl;

import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.system.*;
import cn.hutool.system.oshi.CpuInfo;
import cn.hutool.system.oshi.OshiUtil;
import com.wsd.jing.vo.MonitorVO;
import com.wsd.jing.service.IMonitorService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import oshi.hardware.CentralProcessor;
import oshi.hardware.GlobalMemory;

import java.io.File;
import java.lang.management.RuntimeMXBean;
import java.text.DecimalFormat;
import java.time.format.DateTimeFormatter;
import java.util.HashMap;
import java.util.Map;

/**
 * All rights Reserved, Designed By www.tom.com
 *
 * @author tom
 * @version 1.0.0
 * @projectName: jing
 * @packageName: com.wsd.jing.service.impl
 * @className: MonitorServiceImpl
 * @description 监控服务实现类
 * @createDate 2022/12/7 18:17
 * @copyright 2022/12/7 18:17 www.tom.com Inc. All rights reserved.
 */
@Service
@Slf4j
public class MonitorServiceImpl implements IMonitorService {
    public static final long HOUR = 60 * 60 * 1000;
    public static final long DAY = 24 * 60 * 60 * 1000;

    @Override
    public MonitorVO getServerInfo() {
        MonitorVO monitorDTO = new MonitorVO();
        // cpu信息
        Map cpu = getCpuInfo();
        monitorDTO.setCpuInfo(cpu);

        // 主机信息
        Map system = getSystemInfo();
        monitorDTO.setSystemInfo(system);

        // 内存信息
        Map memoryInfo = getMemoryInfo();
        monitorDTO.setMemoryInfo(memoryInfo);

        // jvm信息
        Map jvmInfo = getJvmInfo();
        monitorDTO.setJvmInfo(jvmInfo);

        // 存储信息
        Map storeInfo = getStoreInfo();
        monitorDTO.setStoreInfo(storeInfo);
        return monitorDTO;
    }

    /**
     * @return Map
     * @author tom
     * @description 查询cpu信息
     * @createDate 2022/12/7 22:34
     */
    private Map getCpuInfo() {
        Map<String, Object> map = new HashMap<>(9);
        CpuInfo cpuInfo = OshiUtil.getCpuInfo();
        CentralProcessor processor = OshiUtil.getHardware().getProcessor();
        DecimalFormat decimalFormat = new DecimalFormat("0.00");
        DecimalFormat decimalFormat1 = new DecimalFormat("0.00%");
        map.put("total", decimalFormat.format((100d - cpuInfo.getFree())));
        map.put("free", decimalFormat1.format(cpuInfo.getFree() * 0.01));
        map.put("system", decimalFormat1.format(cpuInfo.getSys() * 0.01));
        map.put("user", decimalFormat1.format(cpuInfo.getUser() * 0.01));
        map.put("wait", decimalFormat1.format(cpuInfo.getWait() * 0.01));
        map.put("code", processor.getPhysicalPackageCount());
        map.put("physical", processor.getPhysicalProcessorCount());
        map.put("logic", processor.getLogicalProcessorCount());
        map.put("type", processor.getProcessorIdentifier().toString());
        return map;
    }

    /**
     * @param :
     * @return Map
     * @author tom
     * @description 查询系统信息
     * @createDate 2022/12/8 10:20
     */
    private Map getSystemInfo() {
        Map<String, Object> map = new HashMap<>(4);
        HostInfo hostInfo = SystemUtil.getHostInfo();
        OsInfo osInfo = SystemUtil.getOsInfo();
        map.put("name", hostInfo.getName());
        map.put("address", hostInfo.getAddress());
        map.put("arch", osInfo.getArch());
        map.put("os", osInfo.getName() + osInfo.getVersion());
        return map;
    }

    /**
     * @param :
     * @return Map
     * @author tom
     * @description 查询内存信息
     * @createDate 2022/12/8 10:20
     */
    private Map getMemoryInfo() {
        Map<String, Object> map = new HashMap<>(4);
        GlobalMemory memory = OshiUtil.getMemory();
        DecimalFormat decimalFormat = new DecimalFormat("0.00");
        long used = memory.getTotal() - memory.getAvailable();
        map.put("total", FileUtil.readableFileSize(memory.getTotal()));
        map.put("free", FileUtil.readableFileSize(memory.getAvailable()));
        map.put("used", FileUtil.readableFileSize(used));
        map.put("rate", decimalFormat.format(used * 100.0 / memory.getTotal()));
        return map;
    }

    /**
     * @param :
     * @return Map
     * @author tom
     * @description 查询存储信息
     * @createDate 2022/12/8 10:21
     */
    private Map getStoreInfo() {
        Map<String, Object> map = new HashMap<>(4);
        DecimalFormat decimalFormat = new DecimalFormat("0.00");
        long total = 0L;
        long free = 0L;
        File[] files = File.listRoots();
        for (File file : files) {
            total += file.getTotalSpace();
            free += file.getUsableSpace();
        }
        map.put("total", FileUtil.readableFileSize(total));
        map.put("used", FileUtil.readableFileSize(total - free));
        map.put("free", FileUtil.readableFileSize(free));
        map.put("rate", decimalFormat.format((total - free) * 100.0 / total));
        return map;
    }

    private Map getJvmInfo() {
        Map<String, Object> map = new HashMap<>(12);
        JvmInfo jvmInfo = SystemUtil.getJvmInfo();
        JavaRuntimeInfo javaRuntimeInfo = SystemUtil.getJavaRuntimeInfo();
        UserInfo userInfo = SystemUtil.getUserInfo();
        RuntimeMXBean runtimeMxBean = SystemUtil.getRuntimeMXBean();
        String startTime = LocalDateTimeUtil.of(runtimeMxBean.getStartTime()).format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
        String runTime = formatMilliseconds(runtimeMxBean.getUptime());

        map.put("jvmName", jvmInfo.getName());
        map.put("jvmVersion", jvmInfo.getVersion());
        map.put("startTime", startTime);
        map.put("runTime", runTime);
        map.put("jvmParams", runtimeMxBean.getInputArguments().toString());
        map.put("javaVersion", javaRuntimeInfo.getVersion());
        map.put("javaHome", javaRuntimeInfo.getHomeDir());
        map.put("project", userInfo.getCurrentDir());

        DecimalFormat decimalFormat = new DecimalFormat("0.00");
        long used = SystemUtil.getTotalMemory() - SystemUtil.getFreeMemory();
        map.put("total", FileUtil.readableFileSize(SystemUtil.getTotalMemory()));
        map.put("free", FileUtil.readableFileSize(SystemUtil.getFreeMemory()));
        map.put("used", FileUtil.readableFileSize(used));
        map.put("rate", decimalFormat.format(used * 100.0 / SystemUtil.getTotalMemory()));
        return map;
    }

    /**
     * @param time:
     * @return String
     * @author tom
     * @description 格式化毫秒
     * @createDate 2022/12/8 14:06
     */
    private String formatMilliseconds(long time) {
        long day = 0, hour, minute;
        StringBuilder stringBuilder = new StringBuilder();
        if (time >= HOUR) {
            if (time >= DAY) {
                day = time / (24 * 60 * 60 * 1000);
                hour = time / (60 * 60 * 1000) - day * 24;
                stringBuilder.append(day).append("天");
            } else {
                hour = time / (60 * 60 * 1000);
            }
            minute = time - (hour * 60 * 60 * 1000) - (day * 24 * 60 * 60 * 1000);
            stringBuilder.append(hour).append("小时");
            minute = minute / (60 * 1000);
            stringBuilder.append(minute).append("分钟");
        } else {
            stringBuilder.append(time / (60 * 1000)).append("分钟");
        }
        return stringBuilder.toString();
    }
}
